/**
 * $Revision: 1.3 $
 * $Date: 2010/07/14 03:02:35 $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package cn.newgrand.netcall.component;

import org.jivesoftware.resource.Res;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.spark.PresenceManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.VerticalFlowLayout;
import org.jivesoftware.spark.component.panes.CollapsiblePane;
import org.jivesoftware.spark.component.renderer.JPanelRenderer;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;

import cn.newgrand.common.StringUtil;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;

/**
 * 组展示基类,用于界面中一些列表的显示
 * 组下面有子组或者子项(item)
 * Container representing a RosterGroup within the Contact List.
 */
public class ItemGroup extends CollapsiblePane implements MouseListener {
    private List<BaseItem> baseItems = new ArrayList<BaseItem>();
    private List<ItemGroup> itemGroups = new ArrayList<ItemGroup>();
    private List<ItemGroupListener> listeners = new ArrayList<ItemGroupListener>();

    private String groupName;
    private DefaultListModel model;
    private JList baseItemList;
    private boolean sharedGroup;
    private JPanel listPanel;
    
    // Used to display no contacts in list.
//    private final BaseItem noContacts = new BaseItem(Res.getString("group.empty"), null, null);
    private final ListMotionListener motionListener = new ListMotionListener();
    private boolean canShowPopup;
    private LocalPreferences preferences;


    /**
     * Create a new ContactGroup.
     *
     * @param groupName the name of the new ContactGroup.
     */
    public ItemGroup(String groupName) {
        // Initialize Model and UI
        model = new DefaultListModel();
        baseItemList = new JList(model);
        preferences = SettingsManager.getLocalPreferences();
        setTitle(getGroupTitle(groupName));

        // Use JPanel Renderer
        baseItemList.setCellRenderer(new JPanelRenderer());

        this.groupName = groupName;

        listPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
        listPanel.add(baseItemList, listPanel);
        this.setContentPane(listPanel);

//        if (!isOfflineGroup()) {
//            baseItemList.setDragEnabled(true);
//            baseItemList.setTransferHandler(new ContactGroupTransferHandler());
//        }

        // Allow for mouse events to take place on the title bar
        getTitlePane().addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                checkPopup(e);
            }

            public void mouseReleased(MouseEvent e) {
                checkPopup(e);
            }

            public void checkPopup(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    e.consume();
//                    fireContactGroupPopupEvent(e);
                }
            }
        });

        // Items should have selection listener
        baseItemList.addMouseListener(this);

        baseItemList.addKeyListener(new KeyListener() {
            public void keyTyped(KeyEvent keyEvent) {

            }

            public void keyPressed(KeyEvent keyEvent) {
                if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) {
                	BaseItem item = (BaseItem)baseItemList.getSelectedValue();
//                    fireAppSysItemDoubleClicked(item);
                }

//                ContactList.activeKeyEvent = keyEvent;
            }

            public void keyReleased(KeyEvent keyEvent) {
//                ContactList.activeKeyEvent = null;
            }
        });

//        noContacts.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, 12));
//        noContacts.getNicknameLabel().setForeground(Color.GRAY);
//        model.addElement(noContacts);

        // Add Popup Window
        addPopupWindow();
        
       
    }


    /**
     * Adds a <code>BaseItem</code> to the ContactGroup.
     *
     * @param item the BaseItem.
     */
    public void addItem(BaseItem item) {
        // Remove from offline group if it exists
//        removeOfflineAppSysItem(item.getJID());

//        if (model.contains(noContacts)) {
//            model.remove(0);
//        }

//        if (Res.getString("group.offline").equals(groupName)) {
//            item.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, 12));
//            item.getNicknameLabel().setForeground(Color.GRAY);
//        }

//        item.setGroupName(getGroupName());
    	//判断是否已经存在该项
    	for (BaseItem tempItem : baseItems) {
			if(tempItem.getID().equals(item.getID()))
				return ;
		}
    	
        baseItems.add(item);

        List<BaseItem> tempItems = getItems();


        Collections.sort(tempItems, itemComparator);


        int index = tempItems.indexOf(item);


        Object[] objs = baseItemList.getSelectedValues();

        model.insertElementAt(item, index);

        int[] intList = new int[objs.length];
        for (int i = 0; i < objs.length; i++) {
            BaseItem contact = (BaseItem)objs[i];
            intList[i] = model.indexOf(contact);
        }

        if (intList.length > 0) {
            baseItemList.setSelectedIndices(intList);
        }

//        fireAppSysItemAdded(item);
    }

    /**
     * Call whenever the UI needs to be updated.
     */
    public void fireContactGroupUpdated() {
        baseItemList.validate();
        baseItemList.repaint();
        updateTitle();
    }

    public void addGroupItem(ItemGroup contactGroup) {
        final JPanel panel = new JPanel(new GridBagLayout());
        panel.add(contactGroup, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 15, 0, 0), 0, 0));
        panel.setBackground(Color.white);
        contactGroup.setSubPane(true);

        // contactGroup.setStyle(CollapsiblePane.TREE_STYLE);
        listPanel.add(panel);
        itemGroups.add(contactGroup);
    }

    /**
     * Removes a child ContactGroup.
     *
     * @param contactGroup the contact group to remove.
     */
    public void removeBaseGroup(ItemGroup contactGroup) {
        Component[] comps = listPanel.getComponents();
        for (Component comp : comps) {
            if (comp instanceof JPanel) {
                JPanel panel = (JPanel) comp;
                ItemGroup group = (ItemGroup) panel.getComponent(0);
                if (group == contactGroup) {
                    listPanel.remove(panel);
                    break;
                }
            }
        }


        itemGroups.remove(contactGroup);
    }

    public void setPanelBackground(Color color) {
        Component[] comps = listPanel.getComponents();
        for (Component comp : comps) {
            if (comp instanceof JPanel) {
                JPanel panel = (JPanel) comp;
                panel.setBackground(color);
            }
        }

    }

    /**
     * Returns a ContactGroup based on it's name.
     *
     * @param groupName the name of the group.
     * @return the ContactGroup.
     */
    public ItemGroup getItemGroup(String groupName) {
        for (ItemGroup group : new ArrayList<ItemGroup>(itemGroups)) {
            if (group.getGroupName().equals(groupName)) {
                return group;
            }
        }

        return null;
    }

    /**
     * Removes a <code>BaseItem</code>.
     *
     * @param item the BaseItem to remove.
     */
    public void removeItem(BaseItem item) {
    	if(null==item) return ;
        baseItems.remove(item);
        if (baseItems.size() == 0) {
            removeBaseGroup(this);
        }

        model.removeElement(item);
        updateTitle();

//        fireAppSysItemRemoved(item);
    }

    /**
     * Removes an  <code>BaseItem</code> from the  contact model and ui.
     *
     * @param item id the contact item to remove.
     */
    public void removeItem(String itemId) {
        final List<BaseItem> items = new ArrayList<BaseItem>(baseItems);
        for (BaseItem item : items) {
            if (item.getID().equals(itemId)) {
            	removeItem(item);
            }
        }
    }
    
    /**
     * Returns a <code>BaseItem</code> by the displayed name the user has been assigned.
     *
     * @param displayName the displayed name of the user.
     * @return the BaseItem.
     */
    public BaseItem getItemByID(String id) {
        for (BaseItem item : new ArrayList<BaseItem>(baseItems)) {
            if (item.getID().equals(id)) {
                return item;
            }
        }
        return null;
    }

    /**
     * Returns all <code>BaseItem</cod>s in the ContactGroup.
     *
     * @return all BaseItems.
     */
    public List<BaseItem> getItems() {
        final List<BaseItem> list = new ArrayList<BaseItem>(baseItems);
        Collections.sort(list, itemComparator);
        return list;
    }

    /**
     * Returns the name of the ContactGroup.
     *
     * @return the name of the ContactGroup.
     */
    public String getGroupName() {
        return groupName;
    }


    public void mouseClicked(MouseEvent e) {

        Object o = baseItemList.getSelectedValue();
        if (!(o instanceof BaseItem)) {
            return;
        }

        // Iterator through rest
        BaseItem item = (BaseItem)o;
        
        if (e.getClickCount() == 2) {
        	doDoubleClick(item);
        }
        else if (e.getClickCount() == 1) {
//            fireAppSysItemClicked(item);
        }
    }

    public void mouseEntered(MouseEvent e) {
        int loc = baseItemList.locationToIndex(e.getPoint());

        Object o = model.getElementAt(loc);
        if (!(o instanceof BaseItem)) {
            return;
        }

//        baseItemList.setCursor(GraphicUtils.HAND_CURSOR);
    }

//    public void mouseExited(MouseEvent e) {
//        Object o;
//        try {
//            int loc = baseItemList.locationToIndex(e.getPoint());
//            if (loc == -1) {
//                return;
//            }
//
//            o = model.getElementAt(loc);
//            if (!(o instanceof BaseItem)) {
//                ContactInfoWindow.getInstance().dispose();
//                return;
//            }
//        }
//        catch (Exception e1) {
//            Log.error(e1);
//            return;
//        }
//
//        baseItemList.setCursor(GraphicUtils.DEFAULT_CURSOR);
//
//    }

//    public void mousePressed(MouseEvent e) {
//        checkPopup(e);
//    }
//
//    public void mouseReleased(MouseEvent e) {
//        checkPopup(e);
//    }

//    private void checkPopup(MouseEvent e) {
//        if (e.isPopupTrigger()) {
//            // Otherwise, handle single selection
//            int index = baseItemList.locationToIndex(e.getPoint());
//            if (index != -1) {
//                int[] indexes = baseItemList.getSelectedIndices();
//                boolean selected = false;
//                for (int o : indexes) {
//                    if (index == o) {
//                        selected = true;
//                    }
//                }
//
//                if (!selected) {
//                    baseItemList.setSelectedIndex(index);
//                    fireAppSysItemClicked((BaseItem)baseItemList.getSelectedValue());
//                }
//            }
//
//
//            final Collection selectedItems = SparkManager.getChatManager().getSelectedAppSysItems();
//            if (selectedItems.size() > 1) {
//                firePopupEvent(e, selectedItems);
//            }
//            else if (selectedItems.size() == 1) {
//                final BaseItem contactItem = (BaseItem)selectedItems.iterator().next();
//                firePopupEvent(e, contactItem);
//            }
//        }
//    }

    /**
     * Add a <code>ContactGroupListener</code>.
     *
     * @param listener the ContactGroupListener.
     */
    public void addContactGroupListener(ItemGroupListener listener) {
        listeners.add(listener);
    }

    /**
     * Removes a <code>ContactGroupListener</code>.
     *
     * @param listener the ContactGroupListener.
     */
    public void removeBaseGroupListener(ItemGroupListener listener) {
        listeners.remove(listener);
    }

//    private void fireAppSysItemClicked(BaseItem item) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.contactItemClicked(item);
//        }
//    }
//
//    private void fireAppSysItemDoubleClicked(BaseItem item) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.contactItemDoubleClicked(item);
//        }
//    }
//
//
//    private void firePopupEvent(MouseEvent e, BaseItem item) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.showPopup(e, item);
//        }
//    }
//
//    private void firePopupEvent(MouseEvent e, Collection items) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.showPopup(e, items);
//        }
//    }
//
//    private void fireContactGroupPopupEvent(MouseEvent e) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.contactGroupPopup(e, this);
//        }
//    }
//
//    private void fireAppSysItemAdded(BaseItem item) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.contactItemAdded(item);
//        }
//    }
//
//    private void fireAppSysItemRemoved(BaseItem item) {
//        for (AppSysItemGroupListener contactGroupListener : new ArrayList<AppSysItemGroupListener>(listeners)) {
//            contactGroupListener.contactItemRemoved(item);
//        }
//    }

    private void updateTitle() {
//        if (Res.getString("group.offline").equals(groupName)) {
//            setTitle(Res.getString("group.offline"));
//            return;
//        }
//
//        int count = 0;
//        List<BaseItem> list = new ArrayList<BaseItem>(getItems());
//        int size = list.size();
//        for (int i = 0; i < size; i++) {
//            BaseItem it = list.get(i);
////            if (it.isAvailable()) {
////                count++;
////            }
//        }
//
//        setTitle(getGroupTitle(groupName) + " (" + count + " " + Res.getString("online") + ")");
//
//
//        if (model.getSize() == 0) {
////            model.addElement(noContacts);
//        }
    }

    /**
     * Returns the containing <code>JList</code> of the ContactGroup.
     *
     * @return the JList.
     */
    public JList getList() {
        return baseItemList;
    }

    /**
     * Clears all selections within this group.
     */
    public void clearSelection() {
        baseItemList.clearSelection();
    }

    public void removeAllItems() {
        // Remove all users from online group.
        for (BaseItem item : new ArrayList<BaseItem>(getItems())) {
            removeItem(item);
        }
    }


    /**
     * Sorts AppSysItems.
     */
    final Comparator<BaseItem> itemComparator = new Comparator<BaseItem>() {
        public int compare(BaseItem item1, BaseItem item2) {
            return item1.getDisplayName().toLowerCase().compareTo(item2.getDisplayName().toLowerCase());
        }
    };

    public String toString() {
        return getGroupName();
    }

    /**
     * Returns all Selected Contacts within the ContactGroup.
     *
     * @return all selected AppSysItems.
     */
    public List<BaseItem> getSelectedItems() {
        final List<BaseItem> items = new ArrayList<BaseItem>();
        Object[] selections = baseItemList.getSelectedValues();
        final int no = selections != null ? selections.length : 0;
        for (int i = 0; i < no; i++) {
            try {
                BaseItem item = (BaseItem)selections[i];
                items.add(item);
            }
            catch (NullPointerException e) {
                // TODO: Evaluate if we should do something here.
            }
        }
        return items;
    }

    public JPanel getContainerPanel() {
        return listPanel;
    }

    public Collection<ItemGroup> getContactGroups() {
        return itemGroups;
    }

    /**
     * Lets make sure that the panel doesn't stretch past the
     * scrollpane view pane.
     *
     * @return the preferred dimension
     */
    public Dimension getPreferredSize() {
        final Dimension size = super.getPreferredSize();
        size.width = 0;
        return size;
    }

    /**
     * Sets the name of group.
     *
     * @param groupName the contact group name.
     */
    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    /**
     * Returns the "pretty" title of the ContactGroup.
     *
     * @param title the title.
     * @return the new title.
     */
    public String getGroupTitle(String title) {
        int lastIndex = title.lastIndexOf("::");
        if (lastIndex != -1) {
            title = title.substring(lastIndex + 2);
        }

        return title;
    }

    /**
     * Returns true if the group is nested.
     *
     * @param groupName the name of the group.
     * @return true if the group is nested.
     */
    public boolean isSubGroup(String groupName) {
        return groupName.indexOf("::") != -1;
    }

    /**
     * Returns true if this group is nested.
     *
     * @return true if nested.
     */
    public boolean isSubGroup() {
        return isSubGroup(getGroupName());
    }

    /**
     * Returns the underlying container for the JList.
     *
     * @return the underlying container of the JList.
     */
    public JPanel getListPanel() {
        return listPanel;
    }

    /**
     * Adds an internal popup listesner.
     */
    private void addPopupWindow() {
        final Timer timer = new Timer(500, new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                canShowPopup = true;
            }
        });
        baseItemList.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent mouseEvent) {
                timer.start();
            }
            public void mouseExited(MouseEvent mouseEvent) {
                timer.stop();
                canShowPopup = false;
//                ContactInfoWindow.getInstance().dispose();
            }
        });


        baseItemList.addMouseMotionListener(motionListener);
    }
    private class ListMotionListener extends MouseMotionAdapter {
        public void mouseMoved(MouseEvent e) {
            if (!canShowPopup) {
                return;
            }
            if (e == null) {
                return;
            }
//            displayWindow(e);
        }
    }
    
    /**
     * 鼠标移动到联系人上面时更改背景色
     *
     * @param e the mouseEvent that triggered this event.
     */
    private void changeBackGround(MouseEvent e) {
    	int loc = this.getList().locationToIndex(e.getPoint());
    	BaseItem item = (BaseItem)this.getList().getModel().getElementAt(loc);
    	item.setOpaque(true);
    	item.setBackground((Color)UIManager.get("List.focusBackground"));
    }

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		checkPopup(e);
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		checkPopup(e);
	}
	
	private void checkPopup(MouseEvent e) {
        if (e.isPopupTrigger()) {
            // Otherwise, handle single selection
            int index = baseItemList.locationToIndex(e.getPoint());
            if (index != -1) {
                int[] indexes = baseItemList.getSelectedIndices();
                boolean selected = false;
                for (int o : indexes) {
                    if (index == o) {
                        selected = true;
                    }
                }
                if (!selected) {
                    baseItemList.setSelectedIndex(index);
//                    fireContactItemClicked((ContactItem)baseItemList.getSelectedValue());
                }
            }
            final Collection selectedItems = getSelectedItems();
            if (selectedItems.size() > 1) {
                firePopupEvent(e, selectedItems);
            }
            else if (selectedItems.size() == 1) {
                final BaseItem baseItem = (BaseItem)selectedItems.iterator().next();
                firePopupEvent(e, baseItem);
            }
        }
    }
	
	/**
	 * 子类实现右键弹出菜单，重写这个方法
	 * @param e
	 * @param item
	 */
	public  void firePopupEvent(MouseEvent e,BaseItem item){
		
	}
	
	/**
	 * 子类实现右键弹出菜单，重写这个方法
	 * @param e
	 * @param item
	 */
	public void firePopupEvent(MouseEvent e,Collection<BaseItem> items){
		
	}
	
	public void doDoubleClick(BaseItem item){
		//need to override to custom your double event
	}
    
}






